/**
 * 
 */
package xj.toolkit.ebus.unit.fs;

import java.util.ArrayList;
import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;

import xj.toolkit.ebus.Constants;
import xj.toolkit.ebus.EventBus;

/**
 * @author hp
 *
 */
public class FsUnitSourceGroupManager {

	private static final Logger logger = LoggerFactory.getLogger(FsUnitSourceGroupManager.class);

	private Collection<String> pathes;
	private EventBus eventBus;
	private String prefix = null;
	private Collection<FilesystemUnitSourceGroup> groups = new ArrayList<FilesystemUnitSourceGroup>();
	private long timeout;

	private final boolean _enabled;

	public FsUnitSourceGroupManager(final boolean enabled) {
		this._enabled = enabled;
	}

	/**
	 * @return the pathes
	 */
	public Collection<String> getPathes() {
		return pathes;
	}

	/**
	 * @param pathes
	 *            the pathes to set
	 */
	public void setPathes(Collection<String> pathes) {
		this.pathes = pathes;
	}

	/**
	 * @return the eventBus
	 */
	public EventBus getEventBus() {
		return eventBus;
	}

	/**
	 * @param eventBus
	 *            the eventBus to set
	 */
	public void setEventBus(EventBus eventBus) {
		this.eventBus = eventBus;
	}

	/**
	 * @return the prefix
	 */
	public String getPrefix() {
		return prefix;
	}

	/**
	 * @param prefix
	 *            the prefix to set
	 */
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public void start() {
		if (this._enabled) {
			boolean enablePlugin = getBoolean(Constants.SYSCFG_PLUGIN_ENABLE, false);
			if (enablePlugin) {
				pathes = Lists.newArrayList(pathes);
				pathes.add(Constants.PLUGIN_UNITS);

				logger.debug("System's plugin enable, add path[" + Constants.PLUGIN_UNITS + "].");
			}

			for (String path : pathes) {
				FilesystemUnitSourceGroup group = null;

				try {
					group = new FilesystemUnitSourceGroup();

					group.setCheckTimeout(timeout);
					group.setDir(path);
					group.setEventBus(eventBus);
					group.setPrefix(prefix);
					group.start();
					groups.add(group);
					// 主动延时 10 毫秒， 在加载 下一个 unit 文件前，可基本认为当前 unit 已经初始化完成
					// 可在一般情况下（unit文件初始化内容不太多时），保障 unit 按加载顺序进行先后初始化
					Thread.sleep(10);
				} catch (Exception e) {
					logger.warn("failed to start fs unit group for path {}, reason {}", path, e);
				}
			}
		}
	}

	public void stop() {
		for (FilesystemUnitSourceGroup group : groups) {
			try {
				group.stop();
				if (logger.isDebugEnabled()) {
					logger.debug("stop group {} succeed.", group.getDir());
				}
			} catch (Exception e) {
				logger.warn("failed to stop fs unit group for path {}", group.getDir());
			}
		}
		groups.clear();
	}

	/**
	 * @return the timeout
	 */
	public long getTimeout() {
		return timeout;
	}

	/**
	 * @param timeout
	 *            the timeout to set
	 */
	public void setTimeout(long timeout) {
		this.timeout = timeout;
	}
	
    /**
     * Returns the value of the Java system property with the specified
     * {@code key}, while falling back to the specified default value if
     * the property access fails.
     *
     * @return the property value.
     *         {@code def} if there's no such property or if an access to the
     *         specified property is not allowed.
     */
    public static boolean getBoolean(String key, boolean def) {
        String value = System.getProperty(key);
        if (value == null) {
            return def;
        }

        value = value.trim().toLowerCase();
        if (value.isEmpty()) {
            return true;
        }

        if ("true".equals(value) || "yes".equals(value) || "1".equals(value)) {
            return true;
        }

        if ("false".equals(value) || "no".equals(value) || "0".equals(value)) {
            return false;
        }

        logger.warn(
                "Unable to parse the boolean system property '{}':{} - using the default value: {}",
                key, value, def
        );

        return def;
    }
}
